package cn.wolfcode.luowowo.service.impl;

import cn.wolfcode.luowowo.domain.UserInfo;
import cn.wolfcode.luowowo.exception.LogicException;
import cn.wolfcode.luowowo.redis.service.IUserInfoRedisService;
import cn.wolfcode.luowowo.repository.UserInfoRepository;
import cn.wolfcode.luowowo.service.IUserInfoService;
import cn.wolfcode.luowowo.util.AssertUtil;
import cn.wolfcode.luowowo.util.Consts;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;
import org.springframework.web.client.RestTemplate;

import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.UUID;
import java.util.regex.Pattern;

@Service
//@Transactional //事务最后处理
public class UserInfoServiceImpl implements IUserInfoService {

    @Autowired
    private UserInfoRepository repository;

    @Autowired
    private IUserInfoRedisService userInfoRedisService;


    @Override
    public UserInfo get(String id) {
        Optional<UserInfo> optional = repository.findById(id);
        if (optional != null) {
            return optional.get();
        }
        return null;
    }

    public boolean checkPhone(String phone) {
        UserInfo byPhone = repository.findByPhone(phone);
        return byPhone == null;
    }

    @Override
    public void userRegist(String phone, String nickname, String password, String rpassword, String verifyCode) {
        //对注册参数的验证
        //是否为空
        AssertUtil.hasLenth(phone, "手机号码不能为空！");
        AssertUtil.hasLenth(nickname, "昵称不能为空！");
        AssertUtil.hasLenth(password, "密码不能为空！");
        AssertUtil.hasLenth(rpassword, "确认密码不能为空！");
        AssertUtil.hasLenth(verifyCode, "验证码不能为空！");

        //模拟异常
        //int i = 1 / 0;

        //两次密码是否一致
        AssertUtil.isEquals(password, rpassword, "两次输入的密码不一致！");

        //手机号码是否正确：正则
        //"^[1](([3|5|8][\\d])|([4][4,5,6,7,8,9])|([6][2,5,6,7])|([7][^9])|([9][1,8,9]))[\\d]{8}$"
        String role = "^[1](([3|5|8][\\d])|([4][4,5,6,7,8,9])|([6][2,5,6,7])|([7][^9])|([9][1,8,9]))[\\d]{8}$";
        if (!Pattern.matches(role, phone)) {
            throw new LogicException("手机号码格式不规范，请核对后再试！");
        }


        //手机号是否已经被注册
        if (!this.checkPhone(phone)) {//号码已经存在
            throw new LogicException("手机号码已经被注册");
        }

        //验证码是否正确
        //从Redis中查到存好的验证码
        String code = userInfoRedisService.getVerifycode("verify_code:" + phone);
        if (verifyCode == null || !verifyCode.equals(code)) {
            throw new LogicException("验证码失效或错误！");
        }

        //用户注册
        //创建用户：设置默认值，然后保存进数据库
        UserInfo info = new UserInfo();
        info.setNickname(nickname);
        info.setPhone(phone);
        info.setEmail("");
        info.setPassword(password);//密码需要加密
        info.setGender(UserInfo.GENDER_SECRET);
        info.setLevel(1);
        info.setCity("");
        info.setHeadImgUrl("/images/default.jpg");//默认头像
        info.setInfo("");
        info.setState(UserInfo.STATE_NORMAL);
        info.setId(null);


        //保存
        repository.save(info);
    }

    @Override
    public void sendVerifyCode(String phone, String smsUrl, String appkey) {
        //1.生成验证码
        String code = UUID.randomUUID().toString().replace("-", "").substring(0, 4);
        //2.拼接短信内容
        StringBuilder content = new StringBuilder();
        content.append("你好，你的短信验证码为：").append(code).append(",验证码有效时间为").append(Consts.VERIFY_CODE_VAI_TIME).append("分钟。");

        //3.发送短信
        //假装发送
        System.out.println(content);


/*        //真实发送验证码
        //RestTemplate springmvc专门用于发起HTTP请求的操作类
        RestTemplate restTemplate = new RestTemplate();
        //这样写死太low了，要用配置来管理
        //String url = "https://way.jd.com/kaixintong/kaixintong?mobile=13205516161&content=【凯信通】您的验证码是：123456&appkey=87f7d7e66d93f1022d52dfecf6e704ae";
        Map map = restTemplate.getForObject(smsUrl, Map.class,phone,content.toString(),appkey);
        System.out.println(map);
        if (!map.get("code").equals("10000")){
            throw new LogicException("短信发送失败！");
        }*/


        //控制验证码的频率：利用Redis key的递减1来做
        //1.存限制频率的数据到Redis中
        //从Redis中查到还剩几次发送机会
        Long count = userInfoRedisService.getCount(phone);
        //3次之后抛异常
        if (count <= 0) {
            //抛异常之前应该做个什么操作，才能保证5分钟后又可以操作
            //删除频率数据
            userInfoRedisService.deleteCount(phone);
            throw new LogicException("验证次数已达上限，请5分钟后重试！");
        } else {
            //第一次获取，存数据进Redis：  send_count:1370000000:3
            userInfoRedisService.setCount(count.toString(), phone, Consts.SEND_COUNT * 60L);
        }

        //对限制的次数-1： count--
        userInfoRedisService.decrementCount(phone);

        //设置count
        //userInfoRedisService.setCount(newCount.toString(),phone);

        //4.5分钟之后，key失效，又可以重新发送验证码

        //4.将验证码存到Redis中，key：前缀:phone value：verifycode
        userInfoRedisService.setVerifyCode(phone, code);
    }


    @Override
    public UserInfo userLogin(String username, String password) {
        //1:登录操作
        UserInfo userInfo = repository.getByPhoneAndPassword(username, password);
        if (userInfo == null) {
            throw new LogicException("用户名或密码错误，请核对后重试！");
        }
        //将密码设为null，保证安全
        userInfo.setPassword(null);
        return userInfo;
    }

    //查询用户信息
    @Override
    public List<UserInfo> list() {
        return repository.findAll();
    }

    //通过目的地名字查询用户信息
    @Override
    public List<UserInfo> findByCity(String city) {
        return repository.findByCity(city);
    }
}
